//
//  Texture.cpp
//  STDRenderSDK
//
//  Created by 陈学明 on 2023/3/12.
//

#include "STDSTexture.hpp"
#include "STDSGLFunctions.hpp"

STDSTexture::STDSTexture(int _w, int _h) {
    mSizeW = _w;
    mSizeH = _h;
    mbCreated = true;
    mTexId = STDSGLFunctions::createTexture(mSizeW, mSizeH);
    STDSGLFunctions::checkGlError("GxTexture::GxTexture(int _w, int _h)");
}

STDSTexture::STDSTexture(int _w, int _h, GXNS_GL(GLenum) _f) {
    mSizeW = _w;
    mSizeH = _h;
    mbCreated = true;
    mTexId = STDSGLFunctions::createTexture(mSizeW, mSizeH, _f);
    STDSGLFunctions::checkGlError("GxTexture::GxTexture(int _w, int _h, GXNS_GL(GLenum) _f = GL_RGBA)");
}

STDSTexture::STDSTexture(GLuint _tid, int _w, int _h, bool _del) {
    setTexture(_tid, _w, _h, _del);
}

STDSTexture::STDSTexture(const unsigned char *_data, int _w, int _h, GXNS_GL(GLenum) _f, bool _mp) {
    
    mSizeW = _w;
    mSizeH = _h;
    mbCreated = true;
    mTexId = STDSGLFunctions::createTexture();
    STDSGLFunctions::checkGlError("GxTexture::GxTexture(int _w, int _h)");
    load(_data, mSizeW, mSizeH, _f, _mp);
}

STDSTexture::~STDSTexture() {
//    printf("dealloc--STDSTexture\n");
    _release();
}

void STDSTexture::setTexture(GLuint _tid, int _w, int _h, bool _del){
    mTexId = _tid;
    mSizeW = _w;
    mSizeH = _h;
    mbCreated = _del;
}

void STDSTexture::load(const unsigned char *_data, int _w, int _h, GXNS_GL(GLenum) _f, bool _mp) {
    mSizeW = _w;
    mSizeH = _h;
    glBindTexture(GL_TEXTURE_2D, mTexId);
    glTexImage2D(GL_TEXTURE_2D, 0, (GLint)_f, mSizeW, mSizeH, 0, _f, GL_UNSIGNED_BYTE, _data);
    STDSGLFunctions::checkGlError("Texture.load");
    if (_mp) {
        mMinFilter = GL_LINEAR_MIPMAP_LINEAR;
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)mMinFilter);
        glGenerateMipmap(GL_TEXTURE_2D);
        STDSGLFunctions::checkGlError("Texture.load mipmap");
    }
}

void STDSTexture::update(const unsigned char *_data, int _w, int _h, GXNS_GL(GLenum) _f, bool _mp) {
    mSizeW = _w;
    mSizeH = _h;
    glBindTexture(GL_TEXTURE_2D, mTexId);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, mSizeW, mSizeH, _f, GL_UNSIGNED_BYTE, _data);
    STDSGLFunctions::checkGlError("Texture.load");

    if (_mp) {
        mMinFilter = GL_LINEAR_MIPMAP_LINEAR;
        
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)mMinFilter);
        glGenerateMipmap(GL_TEXTURE_2D);
        STDSGLFunctions::checkGlError("Texture.load mipmap");
    }
}

void STDSTexture::active_oes() {
    glActiveTexture(GL_TEXTURE0);
    STDSGLFunctions::checkGlError("Texture.active_oes1");
    glBindTexture(TEXTURE_OES, mTexId);
    STDSGLFunctions::checkGlError("Texture.active_oes2");
}

void STDSTexture::bind() {
    glBindTexture(GL_TEXTURE_2D, mTexId);
    STDSGLFunctions::checkGlError("Texture.bind");
}

void STDSTexture::unbind() {
    glBindTexture(GL_TEXTURE_2D, 0);
    STDSGLFunctions::checkGlError("Texture.bind");
}

void STDSTexture::active(int i) {
    glActiveTexture(GL_TEXTURE0 + i);
    STDSGLFunctions::checkGlError("Texture.active 1");
    glBindTexture(GL_TEXTURE_2D, mTexId);
    STDSGLFunctions::checkGlError("Texture.active 2");
}

void STDSTexture::inactive(int i) {
    glActiveTexture(GL_TEXTURE0 + i);
    glBindTexture(GL_TEXTURE_2D, 0);
    STDSGLFunctions::checkGlError("Texture.inactive");
}

void STDSTexture::setWrapMode(GXNS_GL(GLenum) _wrapS, GXNS_GL(GLenum) _wrapT){
    mWrapS = _wrapS;
    mWrapT = _wrapT;
}

void STDSTexture::setFilterMode(GXNS_GL(GLenum) _minFilter, GXNS_GL(GLenum) _maxFiter){
    mMinFilter = _minFilter;
    mMaxFilter = _maxFiter;
}

bool STDSTexture::ifWork(){
    return mTexId > TEXTURE_NON;
}

bool STDSTexture::isSize(int _w, int _h) {
    return mSizeW == _w && mSizeH == _h;
}

int STDSTexture::getWidth() {
    return mSizeW;
}

int STDSTexture::getHeight() {
    return mSizeH;
}

GLuint STDSTexture::getId() {
    return mTexId;
}

void STDSTexture::_resetMode(){
    // to optimize
}

void STDSTexture::_release() {
    if(!mbCreated)
        return;
    if ((bool)glIsTexture(mTexId)) {
        glDeleteTextures(1, &mTexId);
        mTexId = 0;
    }
}
